﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Universe.SimpleQueue.Tests
{
    static partial class TypicalWorkers
    {
        public static Action<SimpleQueue> ReadFromEmptyQueue()
        {
            return queue =>
            {
                queue.NextDelivery("no such queue");
            };
        }

        public static Action<SimpleQueue> Consume_And_Always_Ack(string queueName)
        {
            return queue =>
            {
                var msg = queue.NextDelivery(queueName);
                if (msg != null)
                {
                    queue.Ack(queueName, msg.Id);
                }
            };
        }

        public static Action<SimpleQueue> Consume_But_Sometimes_Fail(string queueName, decimal failProbability)
        {
            return queue =>
            {
                var msg = queue.NextDelivery(queueName);
                if (msg != null)
                {
                    // processing is here

                    bool isFail;
                    lock (Rand)
                        isFail = Rand.NextDouble() < (double)failProbability;

                    if (isFail)
                    {
                        DateTime progressiveRetry = DateTime.UtcNow.AddSeconds(20 * msg.HandlersCount);
                        queue.Postpone(queueName, msg.Id, deliveryAtUtc: progressiveRetry);
                    }
                    else
                    {
                        queue.Ack(queueName, msg.Id);
                    }
                }
            };
        }

        static public Action<SimpleQueue> Consume_And_Forward_But_Sometimes_Fail(string queueName, string forwardTo, decimal failProbability)
        {
            return queue =>
            {
                var msg = queue.NextDelivery(queueName);
                if (msg != null)
                {
                    // processing is here

                    bool isFail;
                    lock (Rand)
                        isFail = Rand.NextDouble() < (double)failProbability;

                    if (isFail)
                    {
                        DateTime progressiveRetryAt = DateTime.UtcNow.AddSeconds(20 * Math.Min(5,msg.HandlersCount));
                        queue.Postpone(queueName, msg.Id, deliveryAtUtc: progressiveRetryAt);
                    }
                    else
                    {
                        byte[] anotherMessage = new byte[msg.Payload.Length + 1];
                        queue.Publish(forwardTo, anotherMessage);
                        queue.Ack(queueName, msg.Id);
                    }
                }
            };
        }

    }
}
